package cn.brilliantfuture.commentry.operate.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.jboss.wsf.spi.annotation.WebContext;

import cn.brilliantfuture.commentry.entity.AdvertInfo;
import cn.brilliantfuture.commentry.entity.AdvertPubGroup;
import cn.brilliantfuture.commentry.entity.AdvertPubRecord;
import cn.brilliantfuture.commentry.entity.Lockers;
import cn.brilliantfuture.commentry.operate.AdvertApplyMessageRemote;
import cn.brilliantfuture.commentry.operate.AdvertApplyMessageWebService;
import cn.brilliantfuture.commentry.profile.CommEntryProfile;
import cn.brilliantfuture.commentry.util.CommEntryUtil;
import cn.brilliantfuture.commentry.util.DateTimeHelper;

/**
 * 
 * Title: Communication Entry
 * 
 * Author: LiTian
 * 
 * Date: 2012-7-31
 * 
 * Description:
 * 
 */
@Stateless
@WebService(endpointInterface = "cn.brilliantfuture.commentry.operate.AdvertApplyMessageWebService")
@WebContext(contextRoot = "/commentry", urlPattern = "/AdvertApplyMessageWebService")
public class AdvertApplyMessageImpl implements AdvertApplyMessageRemote, AdvertApplyMessageWebService {

	private static Logger logger = Logger.getLogger(AdvertApplyMessageImpl.class);
	
	private static final String[] WEEKS = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六"};

	@PersistenceContext
	EntityManager entityManager;

	private static String dateyWeatherUrl = "/weather-servlet/weatherDayHServlet/weather?par=6&username=nyadmin&password=nyadmin&code=";
	private static String currentWeatherUrl = "/weather-servlet/weatherDayHServlet/weather?par=3&username=nyadmin&password=nyadmin&code=";

	@SuppressWarnings("unchecked")
	@Deprecated
	public String advertApply(String deviceSn) {
		JSONObject result = new JSONObject();
		AdvertPubRecord advertPubRecord = new AdvertPubRecord();

		List<AdvertPubGroup> advertPubGroups = entityManager.createQuery("select distinct apg from AdvertPubGroup apg inner join apg.lockersPubGroups lpg where apg.deleted = 0 and lpg.lockers.device.deviceSn = '" + deviceSn + "'").getResultList();

		if (null != advertPubGroups && advertPubGroups.size() > 0) {
			AdvertPubGroup advertPubGroup = advertPubGroups.get(0);
			
			List<Lockers> lockersList = entityManager.createQuery("select distinct l from Lockers l inner join fetch l.location lo inner join fetch lo.villiage v where l.device.deviceSn = '" + deviceSn + "'").getResultList();
			Lockers lockers = lockersList.get(0);
			
			result.accumulate("screen", advertPubGroup.getScreen());
			result.accumulate("inStyle", advertPubGroup.getInStyle());
			result.accumulate("inSpeed", advertPubGroup.getInSpeed());
			result.accumulate("outStyle", advertPubGroup.getOutStyle());
			result.accumulate("outSpeed", advertPubGroup.getOutSpeed());
			result.accumulate("stayTime", advertPubGroup.getStayTime());

			advertPubRecord.setLockers(lockers);
			advertPubRecord.setScreen(advertPubGroup.getScreen());
			advertPubRecord.setInStyle(advertPubGroup.getInStyle());
			advertPubRecord.setInSpeed(advertPubGroup.getInSpeed());
			advertPubRecord.setOutStyle(advertPubGroup.getOutStyle());
			advertPubRecord.setOutSpeed(advertPubGroup.getOutSpeed());
			advertPubRecord.setStayTime(advertPubGroup.getStayTime());
			advertPubRecord.setUserGroup(advertPubGroup.getUserGroup());
			advertPubRecord.setInsertTime(new Date());
			advertPubRecord.setPlayTime(new Date());
			
			StringBuffer sb = new StringBuffer();

			JSONArray advertInfos = new JSONArray();

			List<AdvertInfo> advertInfoList = entityManager.createQuery("select ai from AdvertInfo ai inner join ai.advertInfoPubGroups aipg where ai.deleted = 0 and ai.advertType = 1 and aipg.advertPubGroup.advertPubGroupId = " + advertPubGroup.getAdvertPubGroupId() + " order by ai.insertTime desc").setMaxResults(1).getResultList();

			if (null != advertInfoList && advertInfoList.size() > 0) {
				JSONObject advertInfo = new JSONObject();
				advertInfo.accumulate("advertInfo", advertInfoList.get(0).getContent());
				advertInfos.add(advertInfo);
				sb.append(advertInfoList.get(0).getContent()).append(",");
			}

			advertInfoList = entityManager.createQuery("select ai from AdvertInfo ai inner join ai.advertInfoPubGroups aipg where ai.deleted = 0 and ai.advertType = 2 and aipg.advertPubGroup.advertPubGroupId = " + advertPubGroup.getAdvertPubGroupId() + " order by ai.insertTime desc").setMaxResults(1).getResultList();

			if (null != advertInfoList && advertInfoList.size() > 0) {
				JSONObject advertInfo = new JSONObject();
				advertInfo.accumulate("advertInfo", advertInfoList.get(0).getContent());
				advertInfos.add(advertInfo);
				sb.append(advertInfoList.get(0).getContent()).append(",");
			}

			if (null != lockers.getLocation().getVilliage().getArea() && null != lockers.getLocation().getVilliage().getArea().getArea()){
			
				StringBuffer[] values = getWeatherInfo(lockers.getLocation().getVilliage().getArea().getArea().getPinyin(), 0);
				
				if (null != values){
					for (int i = 0; i < values.length; i++) {
						JSONObject advertInfo = new JSONObject();
						advertInfo.accumulate("advertInfo", values[i].toString());
						advertInfos.add(advertInfo);
						
						sb.append(values[i].toString());
						if (i < values.length - 1)
							sb.append(",");
					}
					
					CommEntryUtil.advertCacheMap.put(deviceSn, values);
				} else {
					if (CommEntryUtil.advertCacheMap.contains(deviceSn)){
						for (int i = 0; i < CommEntryUtil.advertCacheMap.get(deviceSn).length; i++) {
							JSONObject advertInfo = new JSONObject();
							advertInfo.accumulate("advertInfo", CommEntryUtil.advertCacheMap.get(deviceSn)[i].toString());
							advertInfos.add(advertInfo);
							
							sb.append(CommEntryUtil.advertCacheMap.get(deviceSn).toString());
							if (i < CommEntryUtil.advertCacheMap.get(deviceSn).length - 1)
								sb.append(",");
						}
					}
				}
			}
			result.accumulate("advertInfos", advertInfos);
			
			advertPubRecord.setContent(sb.toString());
			
			entityManager.persist(advertPubRecord);
			entityManager.flush();
		} 

		logger.info("Result -> " + result.toString());
		return result.toString();
	}

	@SuppressWarnings("unchecked")
	public String advertApply2DOT0(String deviceSn) {
		JSONObject result = new JSONObject();
		
		Calendar calendar = Calendar.getInstance();

		List<Lockers> lockersList = entityManager.createQuery("select distinct l from Lockers l inner join fetch l.location lo inner join fetch lo.villiage v where l.device.deviceSn = '" + deviceSn + "'").getResultList();
		
		if (null != lockersList && lockersList.size() > 0){
			Lockers lockers = lockersList.get(0);
			
			result.accumulate("screen", 0);
			result.accumulate("inStyle", 4);
			result.accumulate("inSpeed", 2);
			result.accumulate("outStyle", 3);
			result.accumulate("outSpeed", 2);
			result.accumulate("stayTime", 3);
			
			//String pinyin = lockers.getLocation().getVilliage().getArea().getArea().getPinyin();
			
			//StringBuffer[] values = getWeatherInfo(pinyin, 0);
			StringBuffer[] values = null;
			
			/*if (null == values) {
				logger.info("Remote weather info is null!");
				values = CommEntryUtil.advertCacheMap.get(pinyin);
				List<AdvertPubRecord> advertPubRecords = entityManager.createQuery("select apr from AdvertPubRecord apr where apr.lockers.lockersId = " + lockers.getLockersId() + " group by apr.userGroup.groupId order by apr.advertPlayRecordId desc").setMaxResults(1).getResultList();
				if (advertPubRecords.size() > 0){
					AdvertPubRecord apr = advertPubRecords.get(0);

					values = new StringBuffer[2];
					
					String[] contents = apr.getContent().split("\\|");
					
					if (contents.length >= 2){
						StringBuffer datey = new StringBuffer();
						datey.append(contents[contents.length - 2]);
						values[0] = datey;
						
						StringBuffer current = new StringBuffer();
						current.append(contents[contents.length - 1]);
						values[1] = current;
					}
				}
			} else {
				CommEntryUtil.advertCacheMap.put(pinyin, values);
			}*/
			
			List<AdvertPubGroup> advertPubGroups = null;

			if (lockers.getLockersType().intValue() == 1){
				advertPubGroups = entityManager.createQuery("select distinct apg from AdvertPubGroup apg inner join apg.lockersPubGroups lpg inner join apg.userGroup g where apg.deleted = 0 and g.groupType = 2 and lpg.lockers.device.deviceSn = '" + deviceSn + "'").getResultList();
			} else if (lockers.getLockersType().intValue() == 2){
				advertPubGroups = entityManager.createQuery("select distinct apg from AdvertPubGroup apg inner join apg.lockersPubGroups lpg inner join apg.userGroup g where apg.deleted = 0 and g.groupType = 1 and lpg.lockers.device.deviceSn = '" + deviceSn + "'").getResultList();
			}
			
			JSONArray advertInfos = new JSONArray();
			
			if (null != advertPubGroups && advertPubGroups.size() > 0){
				AdvertPubGroup advertPubGroup = advertPubGroups.get(0);
				
				List<AdvertInfo> advertInfoList = entityManager.createQuery("select ai from AdvertInfo ai inner join ai.advertInfoPubGroups aipg where ai.deleted = 0 and aipg.advertPubGroup.advertPubGroupId = " + advertPubGroup.getAdvertPubGroupId() + " order by ai.insertTime desc").setMaxResults(1).getResultList();
				
				if (null != advertInfoList && advertInfoList.size() > 0){
					AdvertInfo advertInfo = advertInfoList.get(0);
					
					AdvertPubRecord advertPubRecord = new AdvertPubRecord();
					result.element("screen", advertPubGroup.getScreen());
					result.element("inStyle", advertPubGroup.getInStyle());
					result.element("inSpeed", advertPubGroup.getInSpeed());
					result.element("outStyle", advertPubGroup.getOutStyle());
					result.element("outSpeed", advertPubGroup.getOutSpeed());
					result.element("stayTime", advertPubGroup.getStayTime());

					advertPubRecord.setLockers(lockers);
					advertPubRecord.setScreen(advertPubGroup.getScreen());
					advertPubRecord.setInStyle(advertPubGroup.getInStyle());
					advertPubRecord.setInSpeed(advertPubGroup.getInSpeed());
					advertPubRecord.setOutStyle(advertPubGroup.getOutStyle());
					advertPubRecord.setOutSpeed(advertPubGroup.getOutSpeed());
					advertPubRecord.setStayTime(advertPubGroup.getStayTime());
					advertPubRecord.setUserGroup(advertPubGroup.getUserGroup());
					advertPubRecord.setContent(advertInfo.getContent() + (null != values ? "|" + DateTimeHelper.dateTimeToStr(calendar.getTime(), DateTimeHelper.DEFAULT_CN_DATE_FORMATE) + "(" + WEEKS[calendar.get(Calendar.DAY_OF_WEEK) - 1] + ") " + values[0] + "|" + values[1] : ""));
					advertPubRecord.setInsertTime(new Date());
					advertPubRecord.setPlayTime(new Date());
					
					String[] contents = advertInfo.getContent().split("\\|");
					
					for (int i = 0; i < contents.length; i++) {
						advertInfos.add(contents[i]);
					}
					
					entityManager.persist(advertPubRecord);
				}
			}
			
			advertPubGroups = entityManager.createQuery("select distinct apg from AdvertPubGroup apg inner join apg.lockersPubGroups lpg inner join apg.userGroup g where apg.deleted = 0 and g.groupType = 3 and lpg.lockers.device.deviceSn = '" + deviceSn + "'").getResultList();
			
			if (null != advertPubGroups && advertPubGroups.size() > 0){
				AdvertPubGroup advertPubGroup = advertPubGroups.get(0);
				
				List<AdvertInfo> advertInfoList = entityManager.createQuery("select ai from AdvertInfo ai inner join ai.advertInfoPubGroups aipg where ai.deleted = 0 and aipg.advertPubGroup.advertPubGroupId = " + advertPubGroup.getAdvertPubGroupId() + " order by ai.insertTime desc").setMaxResults(1).getResultList();
				
				if (null != advertInfoList && advertInfoList.size() > 0){
					AdvertInfo advertInfo = advertInfoList.get(0);
				
					AdvertPubRecord advertPubRecord = new AdvertPubRecord();
					advertPubRecord.setLockers(lockers);
					advertPubRecord.setScreen(advertPubGroup.getScreen());
					advertPubRecord.setInStyle(advertPubGroup.getInStyle());
					advertPubRecord.setInSpeed(advertPubGroup.getInSpeed());
					advertPubRecord.setOutStyle(advertPubGroup.getOutStyle());
					advertPubRecord.setOutSpeed(advertPubGroup.getOutSpeed());
					advertPubRecord.setStayTime(advertPubGroup.getStayTime());
					advertPubRecord.setUserGroup(advertPubGroup.getUserGroup());
					advertPubRecord.setContent(advertInfo.getContent() + (null != values ? "|" + DateTimeHelper.dateTimeToStr(calendar.getTime(), DateTimeHelper.DEFAULT_CN_DATE_FORMATE) + "(" + WEEKS[calendar.get(Calendar.DAY_OF_WEEK) - 1] + ") " + values[0] + "|" + values[1] : ""));
					advertPubRecord.setInsertTime(new Date());
					advertPubRecord.setPlayTime(new Date());
					
					String[] contents = advertInfo.getContent().split("\\|");
					
					for (int i = 0; i < contents.length; i++) {
						advertInfos.add(contents[i]);
					}	
					
					entityManager.persist(advertPubRecord);
				}
			}
			
			if (null != values) {
				advertInfos.add(DateTimeHelper.dateTimeToStr(calendar.getTime(), DateTimeHelper.DEFAULT_CN_DATE_FORMATE) + "(" + WEEKS[calendar.get(Calendar.DAY_OF_WEEK) - 1] + ") " + values[0].toString());
				advertInfos.add(values[1].toString());
			}
			
			result.accumulate("advertInfos", advertInfos);
		}

		entityManager.flush();
		
		logger.info("Result -> " + result.toString());
		return result.toString();
	}

	private static StringBuffer[] getWeatherInfo(String pingyin, int invokeNum) {
		StringBuffer[] contents = new StringBuffer[2];
		
		invokeNum++;

		String weather = "";
		String temphigh = "";
		String templow = "";
		String wind = "";
		
		String temp = "";
		String sd = "";
		String wd = "";

		try {

			CommEntryProfile profile = CommEntryProfile.getInstance(); 
			
			String datey = invoke("http://" + profile.get(CommEntryProfile.WEATHER_SERVICE_IP) + dateyWeatherUrl + pingyin.toLowerCase());
			
			if ("".equals(datey)){
				return null;
			}
			
			Document dateyDocument = DocumentHelper.parseText(datey);
			Element dateyRoot = dateyDocument.getRootElement();

			contents[0] = new StringBuffer();
			
			for (Iterator it = dateyRoot.elementIterator(); it.hasNext();) {
				Element element = (Element) it.next();

				if ("weatherwindfutures".endsWith(element.getName())) {
					if (element.elementIterator().hasNext()) {
						Element dateyElements = (Element) element.elementIterator().next();
						if (!dateyElements.isTextOnly()) {
							for (Iterator dayIt = dateyElements.elementIterator(); dayIt.hasNext();) {
								Element dateyElement = (Element) dayIt.next();
								if ("weather".equals(dateyElement.getName())) {
									weather = dateyElement.getText();
								}
								if ("temphigh".equals(dateyElement.getName())) {
									temphigh = dateyElement.getText();
								}
								if ("templow".equals(dateyElement.getName())) {
									templow = dateyElement.getText();
								}
								if ("wind".equals(dateyElement.getName())){
									wind = dateyElement.getText();
								}
							}
						}
					}

				}
			}

			String current = invoke("http://" + profile.get(CommEntryProfile.WEATHER_SERVICE_IP) + currentWeatherUrl + pingyin.toLowerCase());

			if ("".equals(current)){
				return null;
			}
			
			Document currentDocument = DocumentHelper.parseText(current);
			Element currentRoot = currentDocument.getRootElement();

			contents[1] = new StringBuffer();
			
			for (Iterator it = currentRoot.elementIterator(); it.hasNext();) {
				Element element = (Element) it.next();

				if (element.isTextOnly()) {
					if ("temp".equals(element.getName())) {
						temp = element.getText();
					}
					if ("sd".equals(element.getName())) {
						sd = element.getText();
					}
					if ("wd".equals(element.getName())) {
						wd = element.getText();
					}
				}
			}

		} catch (DocumentException e) {
			logger.error("Read weather information fail\n" + e.getMessage());
		} catch (IOException e) {
			logger.error("Read profile information fail\n" + e.getMessage());
		}

		if ("".equals(weather) || "".equals(temphigh) || "".equals(templow) || "".equals(wind) || "".equals(temp) || "".equals(sd) || "".equals(wd))
			if (invokeNum > 3)
				return null;
			else
				return getWeatherInfo(pingyin, invokeNum);
			
		if (Integer.parseInt(sd) < 0 || Integer.parseInt(sd) > 100)
			if (invokeNum > 3)
				return null;
			else
				return getWeatherInfo(pingyin, invokeNum);
		
		contents[0].append(temphigh).append("℃~").append(templow).append("℃ ").append(wind);
		contents[1].append("当前温度:").append(temp).append("℃ ").append(" 当前湿度:").append(sd).append("%").append(" 当前风向:").append(wd);
		
		return contents;
	}

	private static String invoke(String invokeUrl) {
		URL url = null;
		HttpURLConnection connection = null;
		InputStream is = null;
		InputStreamReader isr = null;
		BufferedReader br = null;
		String value = "";
		
		try {
			url = new URL(invokeUrl);
			connection = (HttpURLConnection) url.openConnection();
			connection.setReadTimeout(5000);
			connection.connect();
			is = connection.getInputStream();

			isr = new InputStreamReader(is, "GBK");
			br = new BufferedReader(isr);
			int c = -1;
			StringBuilder isb = new StringBuilder();
			while ((c = br.read()) >= 0) {
				isb.append((char) c);
			}
			value = isb.toString();

		} catch (MalformedURLException e) {
			logger.error("Invoke url fail\n" + e.getMessage());
		} catch (IOException e) {
			logger.error("Invoke url fail\n" + e.getMessage());
		} finally {
			try {
				if (is != null) {
					is.close();
				}
				if (isr != null) {
					isr.close();
				}
				if (br != null) {
					br.close();
				}
			} catch (IOException e) {
				logger.error("Invoke url fail\n" + e.getMessage());
			}
			connection.disconnect();
		}

		return value;
	}
}
